package com.game.majiang.algorithm.doudizhu;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

import com.game.majiang.config.DataManager;
import com.game.majiang.config.LogManager;

/**
 * 游戏算法
 * @author 
 */
public class GameAlgorithm {

	/**
	 * 判断牌型
	 * @param list
	 * @return
	 */
	public static CardType jugdeType(List<Card> list) {
		/**
		 * 1、对传递过来的卡牌排序
		 */
		order(list) ;
		/**
		 * 因为之前排序过所以比较好判断
		 */
		int len = list.size();
		/**
		 * 单牌,对子，3不带，4个一样炸弹
		 */
		if (len <= 4) { 
			// 如果第一个和最后个相同，说明全部相同
			if (list.size() > 0 && list.get(0).getWeight()== list.get(len - 1).getWeight()) {
				switch (len) {
				case 1:
					return CardType.c1;
				case 2:
					return CardType.c2;
				case 3:
					return CardType.c3;
				case 4:
					return CardType.c4;
				}
			}

			/**
			 * 双王,化为炸弹返回
			 */
			if (len == 2 && list.get(1).getHuase().get_value()==5)
				return CardType.c4;
			/**
			 * 当第一个和最后个不同时,3带1
			 */
			if (len == 4 && 
				((list.get(0).getWeight() == list.get(len - 2).getWeight()) ||
				list.get(1).getWeight() ==list.get(len - 1).getWeight()))
				return CardType.c31;
			else {
				return CardType.c0;
			}
		}

		/**
		 * 当5张以上时，连字，3带2，飞机，2顺，4带2等等
		 */
		if (len >= 5) {
			/**
			 *  现在按相同数字最大出现次数
			 */
			Card_index card_index = new Card_index();
			for (int i = 0; i < 4; i++)
				card_index.a[i] = new ArrayList<Integer>();

			/**
			 *  求出各种数字出现频率
			 */
			GameAlgorithm.getMax(card_index, list); // a[0,1,2,3]分别表示重复1,2,3,4次的牌

			/**
			 * 3带2 -----必含重复3次的牌
			 */
			if (card_index.a[2].size() == 1 && card_index.a[1].size() == 1 && len == 5)
				return CardType.c32;

			/**
			 * 4带2(单,双)
			 */
			if (card_index.a[3].size() == 1 && len == 6)
				return CardType.c411;
			if (card_index.a[3].size() == 1 && card_index.a[1].size() == 2
					&& len == 8)
				return CardType.c422;
			
			/**
			 * 单连,保证不存在王
			 */
			if (list.get(0).getHuase()!= Huase.King
					&& list.get(0).getWeight()!= 13
					&& (card_index.a[0].size() == len)
					&& (list.get(0).getWeight()
							- list.get(len - 1).getWeight() == len - 1))
				return CardType.c123;

			/**
			 *  连队
			 */
			if (card_index.a[1].size() == len / 2
					&& (Integer)card_index.a[1].get(card_index.a[1].size()-1) != 13
					&& len % 2 == 0
					&& len / 2 >= 3
					&& (list.get(0).getWeight()
							- list.get(len - 1).getWeight() == (len / 2 - 1)))
				return CardType.c1122;

			/**
			 * 飞机
			 */
			if (card_index.a[2].size() == len / 3
					&& (Integer)card_index.a[2].get(card_index.a[2].size()-1) != 13
					&& (len % 3 == 0)
					&& (list.get(0).getWeight()
							- list.get(len - 1).getWeight() == (len / 3 - 1)))
				return CardType.c111222;

			/**
			 * 飞机带n单,n/2对
			 */
			if ((card_index.a[2].size() == len / 4)
					&& len % 4 == 0 
					&& (Integer)card_index.a[2].get(card_index.a[2].size()-1) != 13
					&& ((Integer)card_index.a[2].get(len / 4 -1) - (Integer)card_index.a[2].get(0) == len/4 -1 ))
				return CardType.c11122234;

			/**
			 * 飞机带n双
			 */
			if (card_index.a[2].size() == len / 5
					&& len % 5   == 0
				    && (Integer)card_index.a[2].get(card_index.a[2].size()-1) != 13
					&& card_index.a[1].size() == len / 5
					&& ((Integer)card_index.a[2].get(len / 5 -1) - (Integer)card_index.a[2].get(0) == len/5 -1 ))
				return CardType.c1112223344;

		}
		return CardType.c0;
	}


	/**
	 * 得到最大相同数
	 * @param card_index
	 * @param list
	 */
	public static void getMax(Card_index card_index, List<Card> list) {
		int count[] = new int[14];// 1-13各算一种,王算第14种
		for (int i = 0; i < 14; i++)
			count[i] = 0;
		for (int i = 0, len = list.size(); i < len; i++) {
			if (list.get(i).getHuase() ==Huase.King)
				count[13]++;
			else
				count[list.get(i).getWeight() - 1]++;
		}
		for (int i = 0; i < 14; i++) {
			switch (count[i]) {
			case 1:
				card_index.a[0].add(i + 1);
				break;
			case 2:
				card_index.a[1].add(i + 1);
				break;
			case 3:
				card_index.a[2].add(i + 1);
				break;
			case 4:
				card_index.a[3].add(i + 1);
				break;
			}
		}
	}


	/**
	 * 检查牌的是否能出
	 * @param current 上一次出牌
	 * @param c 用户出的牌
	 * @return
	 */
	public static boolean checkCards(List<Card> pre, List<Card> c) {
	  if(pre == null || pre.size() == 0)
			return true;
		/**
		 * 找出当前最大的牌是哪个电脑出的,c是点选的牌
		 */
		CardType cType = GameAlgorithm.jugdeType(c);

		/**
		 * 如果张数不同直接过滤
		 */
		if (cType != CardType.c4 && c.size() != pre.size())
			return false;

		/**
		 * 比较我的出牌类型
		 */
		if (GameAlgorithm.jugdeType(c) != GameAlgorithm.jugdeType(pre)) {

			if(GameAlgorithm.jugdeType(c) == CardType.c4)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		/**
		 *  比较出的牌是否要大
		 *  王炸弹
		 */
		if (cType == CardType.c4) {
			if (c.size() == 2)
				return true;
			if (pre.size() == 2)
				return false;
		}

		/**
		 * 单牌,对子,3带,4炸弹
		 */
		if (cType == CardType.c1 || cType == CardType.c2
				|| cType == CardType.c3 || cType == CardType.c4) {
			if (c.get(0).getWeight() > pre.get(0).getWeight()) {
				return true;
			} else {
				return false;
			}
		}
		// 顺子,连队，飞机裸
		if (cType == CardType.c123 || cType == CardType.c1122
				|| cType == CardType.c111222) {
			if (c.get(0).getWeight()> pre.get(0).getWeight())
				return true;
			else
				return false;
		}

		/**
		 *   按重复多少排序
		 *   3带1,3带2 ,飞机带单，双,4带1,2,只需比较第一个就行，独一无二的
		 */
		if (cType == CardType.c31 || cType == CardType.c32
				|| cType == CardType.c411 || cType == CardType.c422
				|| cType == CardType.c11122234 || cType == CardType.c1112223344) {
			byte pc = getMax(c); // 我出的牌
			byte pp  = getMax(pre);// 上一次出牌
			if (pc < pp)
				return false;
			else
				return true;
		}
		return false;
	}

	/**
	 * 获得重复牌数最多 并且最大的联牌点数
	 * @param list
	 * @return
	 */
	public static byte getMax(List<Card> list) {
		List<Card> list2 = new ArrayList<Card>(list);
		int len = list2.size();
		int a[] = new int[15];
		for (int i = 0; i < len; i++) {
			a[list2.get(i).getWeight()-1]++;
		}
		byte max = 0;
		for (byte i = 0; i < 15; i++) {
			max = 0;
			for (byte j = 13; j >= 0; j--) {
				if (a[j] > a[max])
					max = j;
			}
		}
		return  max;
	}
	
	/**
	 * 
	 * 初始化牌
	 * 发牌系统
	 */
	public static ArrayList<Card>[] CardInit() {
		Card card[] = new Card[54]; // 定义54张牌
		//扑克牌列表
		ArrayList<Card> playerList[] = new ArrayList[4]; // 定义3个玩家表
		//初始化牌
		for (byte i = 0; i < 54; i++) {
			card[i] = new Card(i+1);
		}
		//打乱顺序
		for(int i=0;i<123;i++){
			Random random=new Random();
			int a=random.nextInt(54);
			int b=random.nextInt(54);
			Card k=card[a];
			card[a]=card[b];
			card[b]=k;
		}
		//开始发牌
		for(int i=0;i<4;i++)
			playerList[i]=new ArrayList<Card>(); //玩家牌
		int t=0;
		for(int i=0;i<54;i++)
		{
			if(i>=51)//地主牌
			{
				playerList[3].add(card[i]);
				continue;
			}
			switch ((t++)%3) {
			case 0:
				playerList[0].add(card[i]);
				break;
			case 1:
				playerList[1].add(card[i]);
				break;
			case 2:
				playerList[2].add(card[i]);
				break;
			}
		}
		for(int i = 0 ; i < 3 ; i ++){
	        order(playerList[i]);
			LogManager.getInstance().Log(" 手牌   *******************  "+ playerList[i]);
		}
		LogManager.getInstance().Log("地主牌："+ playerList[3]);
		return playerList ;
	}
	public static ArrayList<Card>[] CardInitHua() {
		Card card[] = new Card[55]; // 定义55张牌
		//扑克牌列表
		ArrayList<Card> playerList[] = new ArrayList[4]; // 定义3个玩家表
		//初始化牌
		for (byte i = 0; i < 55; i++) {
			card[i] = new Card(i+1);
		}
		//打乱顺序
		for(int i=0;i<123;i++){
			Random random=new Random();
			int a=random.nextInt(55);
			int b=random.nextInt(55);
			Card k=card[a];
			card[a]=card[b];
			card[b]=k;
		}
		//开始发牌
		for(int i=0;i<4;i++)
			playerList[i]=new ArrayList<Card>(); //玩家牌
		int t=0;
		for(int i=0;i<55;i++)
		{
			if(i>=51)//地主牌
			{
				playerList[3].add(card[i]);
				continue;
			}
			switch ((t++)%3) {
			case 0:
				playerList[0].add(card[i]);
				break;
			case 1:
				playerList[1].add(card[i]);
				break;
			case 2:
				playerList[2].add(card[i]);
				break;
			}
		}
		for(int i = 0 ; i < 3 ; i ++){
	        order(playerList[i]);
			LogManager.getInstance().Log(" 手牌   *******************  "+ playerList[i]);
		}
		LogManager.getInstance().Log("地主牌："+ playerList[3]);
		return playerList ;
	}
	/**
	 * 
	 * 初始化牌
	 * 发牌系统
	 */
	public static ArrayList<Card>[] CardInitSiren() {
		Card card[] = new Card[54]; // 定义54张牌
		//扑克牌列表
		ArrayList<Card> playerList[] = new ArrayList[5]; // 定义3个玩家表
		//初始化牌
		for (byte i = 0; i < 54; i++) {
			card[i] = new Card(i+1);
		}
		//打乱顺序
		for(int i=0;i<100;i++){
			Random random=new Random();
			int a=random.nextInt(54);
			int b=random.nextInt(54);
			Card k=card[a];
			card[a]=card[b];
			card[b]=k;
		}
		//开始发牌
		for(int i=0;i<4;i++)
			playerList[i]=new ArrayList<Card>(); //玩家牌
		int t=0;
		for(int i=0;i<54;i++)
		{
			if(i>=51)//地主牌
			{
				playerList[4].add(card[i]);
				continue;
			}
			switch ((t++)%4) {
			case 0:
				playerList[0].add(card[i]);
				break;
			case 1:
				playerList[1].add(card[i]);
				break;
			case 2:
				playerList[2].add(card[i]);
				break;
			case 3:
				playerList[3].add(card[i]);
				break;
			}
		}
		for(int i = 0 ; i < 4 ; i ++){
	        order(playerList[i]);
			LogManager.getInstance().Log(" 手牌   *******************  "+ playerList[i]);
		}
		LogManager.getInstance().Log("地主牌："+ playerList[3]);
		return playerList ;
	}
	public static ArrayList<Card>[] CardInitHuaSiren() {
		Card card[] = new Card[55]; // 定义55张牌
		//扑克牌列表
		ArrayList<Card> playerList[] = new ArrayList[5]; // 定义4个玩家表
		//初始化牌
		for (byte i = 0; i < 55; i++) {
			card[i] = new Card(i+1);
		}
		//打乱顺序
		for(int i=0;i<100;i++){
			Random random=new Random();
			int a=random.nextInt(55);
			int b=random.nextInt(55);
			Card k=card[a];
			card[a]=card[b];
			card[b]=k;
		}
		//开始发牌
		for(int i=0;i<4;i++)
			playerList[i]=new ArrayList<Card>(); //玩家牌
		int t=0;
		for(int i=0;i<55;i++)
		{
			if(i>=51)//地主牌
			{
				playerList[4].add(card[i]);
				continue;
			}
			switch ((t++)%4) {
			case 0:
				playerList[0].add(card[i]);
				break;
			case 1:
				playerList[1].add(card[i]);
				break;
			case 2:
				playerList[2].add(card[i]);
			case 3:
				playerList[3].add(card[i]);
				break;
			}
		}
		for(int i = 0 ; i < 4 ; i ++){
	        order(playerList[i]);
			LogManager.getInstance().Log(" 手牌   *******************  "+ playerList[i]);
		}
		LogManager.getInstance().Log("地主牌："+ playerList[3]);
		return playerList ;
	}
	private static void checkanddeletecards(ArrayList<Card> card, Card cc)
	{
		for(Card c : card)
		{
			if(c._value == cc._value)
			{
				card.remove(c);
				break;
			}
		}
	}
	public static ArrayList<Card>[] CardInitRobot(int index, DoudizhuAIRandomcardsAll AIcards,int huapai ) {
		ArrayList<Card> card = new ArrayList<Card>(); // 定义54张牌
		//扑克牌列表
		ArrayList<Card> playerList[] = new ArrayList[4]; // 定义3个玩家表
		//初始化牌
		if (huapai == 0) {
			for (byte i = 0; i < 54; i++) {
				card.add(new Card((byte) (i+1)));
			}
			//打乱顺序
			for(int i=0;i<100;i++){
				Random random=new Random();
				int a=random.nextInt(54);
				int b=random.nextInt(54);
				Card k=card.get(a);
				card.set(a, card.get(b));
				card.set(b, k);
			}
		} else {
			for (byte i = 0; i < 55; i++) {
				card.add(new Card((byte) (i+1)));
			}
			//打乱顺序
			for(int i=0;i<100;i++){
				Random random=new Random();
				int a=random.nextInt(55);
				int b=random.nextInt(55);
				Card k=card.get(a);
				card.set(a, card.get(b));
				card.set(b, k);
			}
		}
		
		//开始发牌
		for(int i=0;i<4;i++) {
			playerList[i]=new ArrayList<Card>(); //玩家牌
		}
			

		AIcards.clone(DataManager.getInstance().getDoudizhuaiserver().getrandomaivo(huapai));
		if (AIcards != null && AIcards.cardsall.size() > 0) {
			for(int i=0; i<AIcards.cardsall.size(); i++)
			{
				for(int j=0; j<AIcards.cardsall.get(i).cards.size(); j++)
				{
					checkanddeletecards(card, AIcards.cardsall.get(i).cards.get(j));
					playerList[index].add(new Card(AIcards.cardsall.get(i).cards.get(j)._value));
				}
				LogManager.getInstance().Log("AIcards.cardsall.get(i).cards.size():"+AIcards.cardsall.get(i).cards.size());
			}
			for(int i=0; i<AIcards.cardsdizhu.size(); i++)
			{
				for(int j=0; j<AIcards.cardsdizhu.get(i).cards.size(); j++)
				{
					checkanddeletecards(card, AIcards.cardsdizhu.get(i).cards.get(j));
					playerList[3].add(new Card(AIcards.cardsdizhu.get(i).cards.get(j)._value));
				}
			}
			for(int i=0; i<3; i++)
			{
				if(i != index)
				{
					for(int j=0; j<17; j++)
					{
						playerList[i].add(card.get(0));
						card.remove(0);
					}
				}
			}
			
			
			for(int i = 0 ; i < 3 ; i ++){
		        order(playerList[i]);
				LogManager.getInstance().Log("CardInitRobot 手牌   *******************  "+ playerList[i]);
			}
			LogManager.getInstance().Log("地主牌："+ playerList[3]);
		} else {
			LogManager.getInstance().Log("CardInitRobot   没有找到Ai牌");
		}
		
		return playerList ;
	}
	
	public static boolean allBelowTenCards(ArrayList<Card> cards) {
		boolean belowTenCardsBool = true;
		for (Card card : cards) {
			if (card.getWeight() > 8) {
				if (card.getHuase() != Huase.Hua) {
					belowTenCardsBool = false;
					break;
				}
			}
		}
		return belowTenCardsBool;
	}
	
	
	
	
	
	/**
	* 对list排序
	 * @param list
	*/
	public static void order(List<Card> list)
			{
				    Collections.sort(list,new Comparator<Card>() {
					@Override
					public int compare(Card o1, Card o2) {
						 
						int a1= o1.getWeight();
						int a2= o2.getWeight();
				
		                if(a1 > a2)
		                {
		                	return -1;
		                }
		                else if(a1 < a2)
		                {
		                	return 1;
		                }
		                else if(o1.getHuase().get_value() > o2.getHuase().get_value() )
		                {
		                	return 1;
		                }
		                else if(o1.getHuase().get_value() < o2.getHuase().get_value() )
		                {
		                	return -1;
		                }
		                else
		                {
		                	return 0;
		                }
 
					}
				});
			}
}



